/*
 *
 * Copyright (C) 2012 Walter Lütgenau
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package offset.nodes.client.model;

import java.util.LinkedList;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import offset.nodes.client.virtual.model.jcr.SimpleValue;

/**
 *
 * @author Walter Lütgenau
 */
public class StringArrayConverter {

    public static final char DELIMITER = ';';
    public static final char MASK = '!';
    // must not be present in an ordinary string. This is unlikely, but not impossible. I am not happy with this solution.
    public static final String ARRAY_IDENTIFIER = "///ARRAY///";
    String[] properties = null;

    public static boolean isStringArray(String value) {
        return value.indexOf(DELIMITER) >= 0;
    }

    public StringArrayConverter(String[] values) {
        properties = values;
    }

    public StringArrayConverter(Value[] values) throws RepositoryException {
        properties = new String[values.length];
        for (int i = 0; i < properties.length; i++) {
            properties[i] = values[i].getString();
        }
    }

    public StringArrayConverter(String value) {
        properties = split(value);
    }

    public int size() {
        return properties.length;
    }

    public void addString(String value) {
        if (properties != null) {
            String[] result = new String[properties.length + 1];
            System.arraycopy(properties, 0, result, 0, properties.length);
            result[result.length - 1] = value;

            properties = result;
        } else
            properties = new String[]{value};
    }

    @Override
    public String toString() {
        StringBuffer buf = new StringBuffer();
        buf.append(ARRAY_IDENTIFIER);
        for (int i = 0; i < properties.length; i++) {
            buf.append(mask(properties[i]));
            if (i + 1 < properties.length)
                buf.append(DELIMITER);
        }

        return buf.toString();
    }

    public String[] toArray() {
        return properties;
    }

    public Value[] toValueArray() {
        SimpleValue[] values = new SimpleValue[properties.length];
        for (int i = 0; i < values.length; i++) {
            values[i] = new SimpleValue(properties[i]);
        }

        return values;
    }

    public static boolean isArray(String value) {
        return value.startsWith(ARRAY_IDENTIFIER);
    }

    protected String mask(String in) {
        String result = in.replaceAll("" + MASK, "" + MASK + MASK);
        result = result.replaceAll("" + DELIMITER, "" + MASK + DELIMITER);

        return result;
    }

    protected String[] split(String value) {
        if (!isArray(value))
            return new String[]{value};
        value = value.substring(ARRAY_IDENTIFIER.length());

        boolean foundMask = false;
        StringBuffer buf = new StringBuffer();
        LinkedList<String> values = new LinkedList<String>();

        for (int i = 0; i < value.length(); i++) {
            char c = value.charAt(i);

            if (c == DELIMITER)
                if (foundMask) {
                    buf.append(c);
                    foundMask = false;
                } else {
                    values.add(buf.toString());
                    buf = new StringBuffer();
                }
            else if (c == MASK)
                if (!foundMask)
                    foundMask = true;
                else {
                    buf.append(c);
                    foundMask = false;
                }
            else
                buf.append(c);
        }

        if (buf.length() > 0)
            values.add(buf.toString());

        return values.toArray(new String[values.size()]);
    }

    public static void main(String[] args) {
        String[] in = new String[]{"A;!A", "B;!", "!;C"};
        StringArrayConverter c1 = new StringArrayConverter(in);
        String between = c1.toString();
        StringArrayConverter c2 = new StringArrayConverter(between);
        String[] out = c2.toArray();
    }
}
